package com.example.demo.service;

import com.alibaba.druid.support.json.JSONUtils;
import com.example.base.Result;
import com.example.demo.dao.GoodsMapper;
import com.example.demo.dao.OrderMapper;
import com.example.demo.entity.Goods;
import com.example.demo.entity.Orders;
import com.example.exception.BusinessException;
import com.example.rabbitmq.PaymentReq;
import com.example.rabbitmq.RabbitmqConfig;
import com.rabbitmq.tools.json.JSONUtil;
import jakarta.annotation.Resource;
import org.apache.ibatis.javassist.bytecode.ByteArray;
import org.aspectj.weaver.ast.Or;
import org.redisson.api.*;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @description goods
 * @author yixin
 * @date 2025-06-12
 */
@Service
public class GoodsServiceImpl implements GoodsService {

	@Resource
	private GoodsMapper goodsMapper;
    @Resource
    private OrderMapper orderMapper;

    @Autowired(required = false)
    private PaymentService paymentService;
    @Override
    public ResponseEntity<?> insert(Goods goods) {
        if (goods == null) {
            return ResponseEntity.badRequest().body("必要参数缺失");
        }
        goodsMapper.insert(goods);
        return ResponseEntity.ok().build();
    }

    @Override
    public ResponseEntity<?> delete(int id) {
        int ret = goodsMapper.delete(id);
        return ret>0 ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
    }

    @Override
    public ResponseEntity<?> update(Goods goods) {
        int ret = goodsMapper.update(goods);
        return ret>0 ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
    }

    @Override
    public Goods load(int id) {
        Goods goods = goodsMapper.load(id);
        return goods != null ? goods : null;
    }


	@Override
	public Map<String,Object> pageList(int offset, int pagesize) {

		List<Goods> pageList = goodsMapper.pageList(offset, pagesize);
		int totalCount = goodsMapper.pageListCount(offset, pagesize);

		// result
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("pageList", pageList);
		result.put("totalCount", totalCount);

		return result;
	}

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Object> processOrder(int id) throws InterruptedException {
        Orders order = createOrder(id);
        System.out.println(order.getGoodsId());
        // 调用支付服务
        return Result.Ok();
    }


    @Resource
    private RabbitmqService rabbitmqService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Object> processOrderAndPay(int id,String userId) throws InterruptedException {
        Orders order = createOrder(id);
        //System.out.println(order.getGoodsId());

//        Orders order = new Orders();
//        order.setPaid(false);
//        order.setOrderId(1);
//        order.setNumber(1);
        PaymentReq paymentReq = new PaymentReq(order.getOrderId(),new BigDecimal(order.getNumber()*10),userId);
        //rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter()); 已加入配置中
        // 调用支付服务
        //rabbitTemplate.convertAndSend(RabbitmqConfig.paymentExchange,RabbitmqConfig.paymentRouteKey,paymentReq);

        // 异步请求
        rabbitmqService.sendMessage2(paymentReq);
        System.out.println("boom");
        return Result.Ok();
    }



    @Resource
    private RedissonClient redissonClient;

    @Transactional(rollbackFor = Exception.class)
    public Orders createOrder(int id) throws InterruptedException {
        int update = 0;
        
        // 先检查商品库存
        Goods goods2 = load(id);
        int leftNum2 = goods2.getNumber();
        if (leftNum2 == 0) {
            throw new BusinessException("商品已经售空！");
        }
        // 使用分布式锁
        RLock lock = redissonClient.getLock("order:lock:" + id);
        // 会在固定的时间重试
        // boolean locked = lock.tryLock(3, 60, TimeUnit.SECONDS);
        // 默认使用30s 看门狗,但是不会重试
        boolean locked = lock.tryLock();
        if (locked) {
            try {
                Goods goods = load(id);
                int leftNum = goods.getNumber();
                if (leftNum == 0) {
                    throw new BusinessException("商品已经售空！");
                }
                goods.setNumber(leftNum - 1);
                update = goodsMapper.update(goods);
            }catch (Exception e){
              Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
            }
        }
        if (update > 0) {
            Orders order = new Orders();
            order.setGoodsId(id);
            order.setNumber(1);
            int insert = orderMapper.insert(order);
            // insert 1 表示的是更新成功了，但是orderid 的值在order中
            if (insert>0){
                Orders load = orderMapper.load(order.getOrderId());
                return load;
            }
        }
        throw new BusinessException("商品太火爆了，请稍后再试！");
    }

    @Resource
    private RedisTemplate redisTemplate;


    public ResponseEntity<Object> initSecKill(int id){
        Goods load = goodsMapper.load(id);
        //RBucket<Object> bucket = redissonClient.getBucket("stock:" + id);
        //bucket.set(load.getNumber());

        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("stock:" + id, load.getNumber());
        if (aBoolean){
            return Result.Ok();
        }else {
            throw new BusinessException();
        }
    }


    @Override
    @Transactional(rollbackFor ={Exception.class,BusinessException.class})
    public ResponseEntity<Object> seckill(int id) throws InterruptedException {
        // 防刷检查
//        RRateLimiter rateLimiter = redissonClient.getRateLimiter("rate:user:" + UUID.randomUUID().toString());
//        if (!rateLimiter.tryAcquire()) {
//            throw new BusinessException("操作过于频繁，请稍后再试！");
//        }

        int update = 0;

        // 原子操作，多线程下更安全
        RAtomicLong s2 = redissonClient.getAtomicLong("stock:" + id);
        if (s2.get()<=0){
            throw new BusinessException("商品已经售空！");
        }

        // 使用分布式锁
        RLock lock = redissonClient.getLock("order:lock:" + id);
        // 默认使用30s 看门狗,但是不会重试
        //boolean locked = lock.tryLock();
        boolean locked = lock.tryLock(100, 10000, TimeUnit.MILLISECONDS);
        if (locked) {
            try {
                // 原子操作，多线程下更安全
                RAtomicLong stock = redissonClient.getAtomicLong("stock:" + id);
                long newStock = stock.decrementAndGet();
                if (newStock < 0){
                    stock.incrementAndGet();
                    throw new BusinessException("商品已经售空！");
                }
                Goods goods = new Goods();
                goods.setGoodId(id);
                update = goodsMapper.update(goods);
            }catch (Exception e){
                Thread.currentThread().interrupt();
                throw new BusinessException("系统繁忙，请稍后再试！");
            } finally {
                lock.unlock();
            }
        }
        if (update == 0) {
            throw new BusinessException("商品库存更新失败，请稍后再试！");
            //throw new BusinessException("商品太火爆了，请稍后再试！");
        }
        // 创建订单
        Orders order = new Orders();
        order.setGoodsId(id);
        order.setNumber(1);
        int insert = orderMapper.insert(order);
        if (insert == 0) {
            throw new BusinessException("订单创建失败，请稍后再试！");
            //throw new BusinessException("商品太火爆了，请稍后再试！");
        }
        Orders load = orderMapper.load(order.getOrderId());
        return new Result().Ok(load);
    }

}